package com.xw.comm.service.impl;

import com.xw.comm.entity.Common;
import com.xw.comm.service.SerialPortService;
import com.xw.comm.service.SerialService;
import com.xw.comm.utils.KeyUtil;
import com.xw.comm.utils.SerialUtil;
import gnu.io.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.TooManyListenersException;

/**
 *
 * @author xiongwei_vendor
 * @date 2020/12/8 19:17
 */
@Slf4j
@Service
public class SerialServiceImpl implements SerialService {

    /**
     * 符号与按键集合
     */
    private static Map<String, Byte> keyCommMap;

    @Autowired
    SerialPortService serialPortService;

    @Override
    public void start(String com) throws NoSuchPortException, PortInUseException, UnsupportedCommOperationException, TooManyListenersException {
        if (null == keyCommMap) {
            keyCommMap = KeyUtil.getKeys();
        }
        serialPortService.start(com);
    }

    @Override
    public void stop(String com) {
        serialPortService.stop(com);
    }

    @Override
    public boolean sendMessage(byte[] data) {
        return serialPortService.sendMessage(data);
    }

    /**
     * 发送一个byte的数据
     *
     * @param data 发送的数据
     * @return 是否发送
     */
    private boolean sendMessage(byte data) {
        return sendMessage(new byte[]{data});
    }

    @Override
    public boolean sendMessage(String data) {
        if (null != keyCommMap && keyCommMap.containsKey(data)) {
            return sendMessage(new byte[]{keyCommMap.get(data)});
        } else {
            return false;
        }
    }

    @Override
    public void core() throws InterruptedException {
        runKey();
    }

    @Override
    public List<String> findCommList() throws InterruptedException {
        return SerialUtil.getCommon();
    }

    @Override
    public void windowsComm() throws InterruptedException {
        sendMessageAndWait(keyCommMap.get(Common.RIGHT), 2100L);

        sendMessageAndWait(keyCommMap.get(Common.DOWN), 1000L);

        sendMessageAndWait(keyCommMap.get(Common.LEFT), 2000L);

        sendMessageAndWait(keyCommMap.get(Common.UP), 1000L);

        sendReleaseTime200(keyCommMap.get("f"));
        Thread.sleep(2000);
    }

    @Async
    private void runKey() {
        try {
            Thread.sleep(2000);
            runCoreKey();
        } catch (InterruptedException e) {
            log.info("出现异常", e);
            Thread.currentThread().interrupt();
        }
    }

    private void runCoreKey() throws InterruptedException {

        sendAndRelease(keyCommMap.get(Common.LEFT), 20L);

        sendMessageAndWait(keyCommMap.get(Common.LEFT), 3000L);

        sendAndRelease(keyCommMap.get(Common.RIGHT));

        sendReleaseTime200(keyCommMap.get("a"));

        sendReleaseTime200(keyCommMap.get("s"));

        sendReleaseTime200(keyCommMap.get("d"));

        sendReleaseTime200(keyCommMap.get("f"));
        Thread.sleep(2000);

        sendReleaseTime200(keyCommMap.get("g"));
        Thread.sleep(2000);

        sendReleaseTime200(keyCommMap.get("h"));
        Thread.sleep(2000);

        sendReleaseTime200(keyCommMap.get("LEFT_ALT"));

    }

    /**
     * 发送键命令，并且延迟10秒，然后发送按键释放命令，并且延迟10S
     *
     * @param data 发送数据
     * @throws InterruptedException 中断异常
     */
    @Override
    public void sendAndRelease(byte data) throws InterruptedException {
        sendAndRelease(data, 30L);
    }

    /**
     * 发送键命令，并且延迟10秒，然后发送按键释放命令，并且延迟10S
     *
     * @param data 发送数据
     * @throws InterruptedException 中断异常
     */
    @Override
    public void sendReleaseTime200(byte data) throws InterruptedException {
        sendAndRelease(data, 30L, 200L);
    }

    @Override
    public void sendAndReleaseDouble(byte data) throws InterruptedException {
        sendAndRelease(data, 30L);
        Thread.sleep(100L);
        sendMessage(data);
    }

    @Override
    public void sendRelease() throws InterruptedException {
        sendMessage((byte) 0);
        Thread.sleep(20L);
    }

    /**
     * 发送键命令，并且延迟指定时间，然后发送按键释放命令，并且延迟10S
     *
     * @param data    命令值
     * @param timeout 延迟时间
     * @throws InterruptedException 中断异常
     */
    private void sendAndRelease(byte data, long timeout) throws InterruptedException {
        sendAndRelease(data, timeout, 50L);
    }

    /**
     * 发送键命令，并且延迟指定时间，然后发送按键释放命令，并且延迟指定时间
     *
     * @param data           命令值
     * @param timeout        延迟时间
     * @param releaseTimeout 按键释放延迟时间
     * @throws InterruptedException 中断异常
     */
    private void sendAndRelease(byte data, long timeout, long releaseTimeout) throws InterruptedException {
        sendMessageAndWait(data, timeout);
        sendMessageAndWait((byte) 0, releaseTimeout);
    }


    /**
     * 发送数据并且等待一定时间
     *
     * @param data    发送的字节码
     * @param timeout 时间，毫秒
     * @throws InterruptedException 中断异常
     */
    private void sendMessageAndWait(byte data, long timeout) throws InterruptedException {
        sendMessage(data);
        Thread.sleep(timeout);
    }


}
